/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package elaborate.vwbe2.annotation;

import elaborate.vwbe.annotation.Annotation;
import elaborate.vwbe.annotation.CodeSegment;
import elaborate.vwbe.annotation.CommentSegment;
import elaborate.vwbe.annotation.SrcSegment;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author lendle
 */
public class DefaultAnnotationAnalyzer implements AnnotationAnalyzer{

    public List<AnnotatedContent> analyze(List<CodeSegment> codeSegments) throws AnalyzerException {
        List<AnnotatedContent> ret=new ArrayList<AnnotatedContent>();
        List<CodeSegment> copiedSegments=new ArrayList<CodeSegment>(codeSegments);
        //annotations that haven't been associated with contents
        List<Annotation> bufferedAnnotations=new ArrayList<Annotation>();
        while(copiedSegments.isEmpty()==false){
            CodeSegment codeSegment=copiedSegments.remove(0);
            //System.out.println("segment="+codeSegment.getClass()+":"+codeSegment.getValue());
            if(codeSegment instanceof CommentSegment){
                //there can be annotations inside
                CommentSegment comment=(CommentSegment) codeSegment;
                List<Annotation> annotations=comment.getAnnotations();
                bufferedAnnotations.addAll(annotations);
            }
            else if((!bufferedAnnotations.isEmpty()) && (codeSegment instanceof SrcSegment)){
                SrcSegment src=(SrcSegment) codeSegment;
                //see if annotations should be applied on this src segment
                String value=src.getValue();
                String annotatedContent=null;
                boolean inApplicableTarget=true;
                while(inApplicableTarget/* && copiedSegments.isEmpty()==false*/){
                    if(value!=null && value.trim().length()>0){
                        //meaningful content
                        //look for "function" or "{" (block start)
                        value=value.trim();
                        if(value.startsWith("function ") || value.startsWith("{")){
                            //should apply buffered annotation to a function/generic block
                            int closeIndex=this.findBlockCloseIndex(value, value.indexOf('{'));
                            //System.out.println("closeIndex="+closeIndex);
                            if(closeIndex==-1){
                                StringBuffer bufferedContent=new StringBuffer(value);
                                while(closeIndex==-1){
                                    //expand the code block until it can be successfully closed
                                    if(copiedSegments.isEmpty()){
                                        AnalyzerException ex=new AnalyzerException("Unable to analyze a code segment.");
                                        ex.setSourceSegment(codeSegment);
                                        throw ex;
                                    }
                                    CodeSegment nextCodeSegment=copiedSegments.remove(0);
                                    if(nextCodeSegment instanceof SrcSegment){
                                        bufferedContent.append(((SrcSegment)nextCodeSegment).getValue());
                                    }
                                    value=bufferedContent.toString();
                                    closeIndex=this.findBlockCloseIndex(value, value.indexOf('{'));
                                }
                            }
                            annotatedContent=value.substring(0, closeIndex+1);
                            //construct an AnnotatedContent instance
                            AnnotatedContent _annotatedContent=new AnnotatedContent();
                            _annotatedContent.setContent(annotatedContent);
                            _annotatedContent.getAnnotations().addAll(bufferedAnnotations);
                            bufferedAnnotations.clear();
                            inApplicableTarget=false;
                            ret.add(_annotatedContent);
                        }
                        else{
                            //give up buffered annotations
                            bufferedAnnotations.clear();
                            inApplicableTarget=false;
                        }
                    }
                }
            }
        }
        return ret;
    }
    /**
     * 
     * @param str
     * @return 
     */
    private int findBlockCloseIndex(String str, int startAt){
        int unMatchedParenthesisCount=0;
        for(int i=startAt; i<str.length(); i++){
            if(str.charAt(i)=='{'){
                unMatchedParenthesisCount++;
            }
            else if(str.charAt(i)=='}'){
                unMatchedParenthesisCount--;
            }
            if(unMatchedParenthesisCount==0){
                return i;
            }
        }
        return -1;
    }
}
